//
// Created by ole on 24-8-21.
//

#include "BasePlugin.h"

#include <utility>
#include "PluginManager.h"
#include "../../utils/Log.h"

BasePlugin::BasePlugin(std::string name, std::string version) : TAG(name),
                                                                name(std::move(name)),
                                                                version(std::move(version)),
                                                                started(false) {
    Log::d(TAG, "+ Constructed. ");
    sInstance = this;
}

BasePlugin::~BasePlugin() {
    Log::d(TAG, "~ Destructed.");
}

void BasePlugin::setIPCManager(const std::shared_ptr<IPCManager> &ipcManager) {
    this->ipcManager = ipcManager;
}

std::string BasePlugin::getName() {
    std::lock_guard<std::mutex> lock(memberMutex);
    return name;
}

std::string BasePlugin::getVersion() {
    std::lock_guard<std::mutex> lock(memberMutex);
    return version;
}

bool BasePlugin::isStarted() {
    std::lock_guard<std::mutex> lock(memberMutex);
    return started;
}

bool BasePlugin::start() {
    ; {
        std::lock_guard<std::mutex> lock(memberMutex);

        if (started) {
            Log::e(TAG, "Plugin has started.");
            return false;
        }
        if (!onStart()) {
            Log::e(TAG, "Plugin start failed.");
            return false;
        }

        started = true;
    }

    Log::e(TAG, "Plugin started.");
    notifyStateChanged("started");

    return true;
}

bool BasePlugin::stop() {
    ; {
        std::unique_lock<std::mutex> lock(memberMutex);
        if (!started) {
            Log::e(TAG, "Plugin has stopped.");
            return false;
        }
        if (!onStop()) {
            Log::e(TAG, "Plugin stop failed.");
            return false;
        }
        started = false;
    }

    Log::e(TAG, "Plugin stopped.");
    notifyStateChanged("stopped");
    return true;
}

void BasePlugin::notifyStateChanged(const std::string &state) {
    Log::e(TAG, "notifyStateChanged: " + state);
    const auto message = std::make_shared<Message>("/core/plugin/state", "onStateChanged");
    message->putString("name", getName());
    message->putString("name", "PluginName");
    message->putString("state", state);
    publishMessage(message);
}

void BasePlugin::subscribe(const std::shared_ptr<Topic> &topic,
                           const std::shared_ptr<MessageReceiver> &receiver) const {
    ipcManager->subscribe(topic, receiver);
}

void BasePlugin::unsubscribe(const std::shared_ptr<Topic> &topic,
                             const std::shared_ptr<MessageReceiver> &receiver) const {
    ipcManager->unsubscribe(topic, receiver);
}

void BasePlugin::publishMessage(const std::shared_ptr<Message> &msg) const {
    ipcManager->publishMessage(msg);
}
